package org.framework.lazy.cloud.network.heartbeat.protocol.handler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyByteBuf;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;


@Slf4j
public class NettyHttpProxyBackendHandler extends SimpleChannelInboundHandler<NettyByteBuf> {


    static void closeOnFlush(Channel ch) {
        if (ch.isActive()) {
            ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * Is called for each message of type {@link I}.
     *
     * @param ctx          the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
     *                     belongs to
     * @param nettyByteBuf the message to handle
     * @throws Exception is thrown if an error occurred
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, NettyByteBuf nettyByteBuf) throws Exception {
        Channel channel = ctx.channel();
        byte[] bytes = nettyByteBuf.getData();
        log.debug("bytes.length:{}", bytes.length);
        log.debug("接收客户端真实服务数据:{}", new String(bytes));
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
        // 将二进制数组转换成 ByteBuf 然后进行发送
        ByteBuf realBuf = nextChannel.config().getAllocator().buffer(bytes.length);
        realBuf.writeBytes(bytes);

        nextChannel.writeAndFlush(realBuf);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
        closeOnFlush(nextChannel);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        closeOnFlush(ctx.channel());
    }
}